﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Net.DataTransfer.Base
{
    /// <summary>
    /// 数据传输消息基类
    /// </summary>
    public abstract class DataTransferMesseageBaseAbs : TransferDataAbs
    {
        /********************************************************************************
         * 字段       数据类型        数据大小(byte)         说明
         * 同步字     UInt32          4 
         * 版本号     byte            1 
         * 资源标识   Int32           4 
         * 消息类型   byte            1
         * 数据包长度 Int32           4                      (不包含头的消息数据长度)
         ********************************************************************************/

        /// <summary>
        /// 包头最小大写
        /// </summary>
        public const int HEAD_SIZE = 14;



        /// <summary>
        /// 同步字
        /// </summary>
        public const uint SYNC = 0xFEEF9FF9;

        /// <summary>
        /// 版本号
        /// </summary>
        public const byte VER = 1;

        /// <summary>
        /// 资源标识
        /// </summary>
        public int RID { get; set; }

        /// <summary>
        /// 消息类型
        /// </summary>
        public byte MessageType { get; private set; }





        /// <summary>
        /// 构造函数
        /// </summary>
        public DataTransferMesseageBaseAbs(byte messageType)
            : base()
        {
            this.MessageType = messageType;
        }





        /// <summary>
        /// 获取要写的数据总长度
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        protected override long GetWriteDataLength()
        {
            return HEAD_SIZE + this.GetMessageDataLength();
        }

        /// <summary>
        /// 获取消息数据长度,不包含头
        /// </summary>
        /// <returns>消息数据长度</returns>
        protected abstract long GetMessageDataLength();





        /// <summary>
        /// 写数据
        /// </summary>
        /// <param name="bufferData">目标数据</param>
        /// <param name="writer"></param>
        protected override void WriteData(BufferData bufferData, BinaryWriter writer)
        {
            writer.Write(SYNC);//同步字
            writer.Write(VER);//版本号
            writer.Write(this.MessageType);//消息类型
            writer.Write((int)this.GetBufferLength());//数据长度(不包含头的消息数据长度)
            writer.Write(this.RID);//资源标识

            this.WriteMessageData(bufferData, writer);
        }

        /// <summary>
        /// 写消息数据
        /// </summary>
        /// <param name="bufferData">目标数据</param>
        /// <param name="writer"></param>
        /// <exception cref="NotImplementedException"></exception>
        protected abstract void WriteMessageData(BufferData bufferData, BinaryWriter writer);





        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="sourceData">原始数据</param>
        /// <param name="reader">数据读取器</param>
        protected override void ReadData(BufferData sourceData, BinaryReader reader)
        {
            this.ReadMessageData(sourceData, reader);
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="sourceData">原始数据</param>
        /// <param name="reader">数据读取器</param>
        /// <exception cref="NotImplementedException"></exception>
        protected abstract void ReadMessageData(BufferData sourceData, BinaryReader reader);


        /// <summary>
        /// 解析数据包
        /// </summary>
        /// <param name="sourceData">原始数据</param>
        /// <param name="reader">数据读取器</param>
        public void Parse(BufferData sourceData, BinaryReader reader)
        {
            this.ReadMessageData(sourceData, reader);
        }
    }


    /// <summary>
    /// 数据传输资源类型常量定义类
    /// </summary>
    internal class DataTransferRIDTypeConstant
    {
        /// <summary>
        /// 内存数据
        /// </summary>
        public const byte MEMORY = 1;

        /// <summary>
        /// 文件
        /// </summary>
        public const byte FILE = 2;

    }

}
